/**********************************************
** @Des: This file ...
** @Author: haodaquan
** @Date:   2017-09-08 00:24:25
** @Last Modified by:   haodaquan
** @Last Modified time: 2017-09-17 10:12:06
***********************************************/

package libs

import (
	"crypto/md5"
	"fmt"
	"math/rand"
	"regexp"
	"time"
	"strconv"
	"github.com/tealeg/xlsx"
	"github.com/astaxie/beego/context"
	"net/url"
)

var emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")

func Md5(buf []byte) string {
	hash := md5.New()
	hash.Write(buf)
	return fmt.Sprintf("%x", hash.Sum(nil))
}

func SizeFormat(size float64) string {
	units := []string{"Byte", "KB", "MB", "GB", "TB"}
	n := 0
	for size > 1024 {
		size /= 1024
		n += 1
	}

	return fmt.Sprintf("%.2f %s", size, units[n])
}

func IsEmail(b []byte) bool {
	return emailPattern.Match(b)
}

func Password(len int, pwdO string) (pwd string, salt string) {
	salt = GetRandomString(4)
	defaultPwd := "123456"
	if pwdO != "" {
		defaultPwd = pwdO
	}
	pwd = Md5([]byte(defaultPwd + salt))
	return pwd, salt
}

// 生成32位MD5
// func MD5(text string) string{
//    ctx := md5.New()
//    ctx.Write([]byte(text))
//    return hex.EncodeToString(ctx.Sum(nil))
// }

//生成随机字符串
func GetRandomString(lens int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	result := []byte{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < lens; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}

//1:t1>t2
//0:t1=t2
//-1:t1<t2
func CompareTime(t1, t2 time.Time) int {
	t1Str := t1.Format("20060102150405")
	t2Str := t2.Format("20060102150405")

	i1, _ := strconv.ParseInt(t1Str, 10, 0)
	i2, _ := strconv.ParseInt(t2Str, 10, 0)
	if i1 > i2 {
		return 1
	} else if i1 < i2 {
		return -1
	}
	return 0
}

//func FormatExcel(output *context.BeegoOutput, list []map[string]string, tableHead map[string]string) {
//	if len(list) == 0 {
//		return
//	}
//	keys := make([]string, 0)
//	for k, _ := range list[0] {
//		keys = append(keys, k)
//	}
//	sort.Strings(keys)
//
//	var file *xlsx.File
//	var sheet *xlsx.Sheet
//	var row *xlsx.Row
//	var cell *xlsx.Cell
//
//	file = xlsx.NewFile()
//	sheet, _ = file.AddSheet("Sheet1")
//	row = sheet.AddRow()
//	for _, v := range keys {
//		cell = row.AddCell()
//		if head,find := tableHead[v];find {
//			cell.Value = head
//		}
//	}
//	for _, v := range list {
//		row = sheet.AddRow()
//		for _, k := range keys {
//			cell = row.AddCell()
//			cell.Value = v[k]
//		}
//	}
//	output.Status = 200
//	output.Header("Content-Disposition", "attachment; filename="+url.QueryEscape("file.xlsx"))
//	output.Header("Content-Description", "File Transfer")
//	output.Header("Content-Type", "application/octet-stream")
//	output.Header("Content-Transfer-Encoding", "binary")
//	file.Write(output.Context.ResponseWriter)
//}
// 格式化模板
func FormatName(in string)(out string){
	if in == ""{
		return "无"
	}
	return in
}
// 和现在时间进行比较
func CompareNow(releaseTime string) bool{
	now := time.Now().Format("2006-01-02 15:04:05")
	if releaseTime < now {
		return true
	}
	return false
}

// 字符串转 time
func StrToTime(str string) time.Time{
	//获取本地location
	toBeCharge := str                             //待转化为时间戳的字符串 注意 这里的小时和分钟还要秒必须写 因为是跟着模板走的 修改模板的话也可以不写
	timeLayout := "2006-01-02 15:04:05"                             //转化所需模板
	loc, _ := time.LoadLocation("Local")                            //重要：获取时区
	theTime, _ := time.ParseInLocation(timeLayout, toBeCharge, loc) //使用模板在对应时区转化为time.time类型
	return theTime
}

// 字符串转 time
func StrToTimeDay(str string) time.Time{
	//获取本地location
	toBeCharge := str                             //待转化为时间戳的字符串 注意 这里的小时和分钟还要秒必须写 因为是跟着模板走的 修改模板的话也可以不写
	timeLayout := "2006-01-02"                             //转化所需模板
	loc, _ := time.LoadLocation("Local")                            //重要：获取时区
	theTime, _ := time.ParseInLocation(timeLayout, toBeCharge, loc) //使用模板在对应时区转化为time.time类型
	return theTime
}

//截取字符串 start 起点下标 length 需要截取的长度
func Substr(str string, start int, length int) string {
	rs := []rune(str)
	rl := len(rs)
	end := 0

	if start < 0 {
		start = rl - 1 + start
	}
	end = start + length

	if start > end {
		start, end = end, start
	}

	if start < 0 {
		start = 0
	}
	if start > rl {
		start = rl
	}
	if end < 0 {
		end = 0
	}
	if end > rl {
		end = rl
	}

	return string(rs[start:end])
}

func FormatExcel(output *context.BeegoOutput, list []map[string]string, tableHead map[int]map[string]string) {
	if len(list) == 0 {
		return
	}
	keys := make([]string, 0)
	for i := 0;i < len(tableHead);i++{
		if head,find := tableHead[i];find{
			for m,_ := range head{
				keys = append(keys, m)
			}
		}
	}
	var file *xlsx.File
	var sheet *xlsx.Sheet
	var row *xlsx.Row
	var cell *xlsx.Cell

	file = xlsx.NewFile()
	sheet, _ = file.AddSheet("Sheet1")
	row = sheet.AddRow()
	for k, v := range keys {
		cell = row.AddCell()
		if head,find := tableHead[k][v];find {
			cell.Value = head
		}
	}
	for _, v := range list {
		row = sheet.AddRow()
		for _, k := range keys {
			cell = row.AddCell()
			cell.Value = v[k]
		}
	}
	output.Status = 200
	output.Header("Content-Disposition", "attachment; filename="+url.QueryEscape("file.xlsx"))
	output.Header("Content-Description", "File Transfer")
	output.Header("Content-Type", "application/octet-stream")
	output.Header("Content-Transfer-Encoding", "binary")
	file.Write(output.Context.ResponseWriter)
}